import sys
sys.path.append("..")
import pyrtl
from  pyrtl import GPUSim
import or1200_definitions

width = or1200_definitions.OR1200_OPERAND_WIDTH

class Or1200sprs(object):
    def __init__(self):
        # Internal CPU interface
        self.rst = pyrtl.Input(bitwidth=1, name='sprs_rst')  # Reset
        self.flagforw = pyrtl.Input(bitwidth=1, name='sprs_flagforw')    # From ALU
        self.flag_we = pyrtl.Input(bitwidth=1, name='sprs_flag_we')      # From ALU
        self.cyforw = pyrtl.Input(bitwidth=1, name='sprs_cyforw')        # From ALU
        self.cy_we = pyrtl.Input(bitwidth=1, name='sprs_cy_we')          # From ALU
        self.addrbase = pyrtl.Input(bitwidth=width, name='sprs_addrbase')    # SPR base address
        self.addrofs = pyrtl.Input(bitwidth=16, name='sprs_addrofs')     # SPR offset
        self.dat_i = pyrtl.Input(bitwidth=width, name='sprs_dat_i')      # SPR write data
        self.alu_op = pyrtl.Input(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH, name='sprs_alu_op') # ALU operation
        self.branch_op = pyrtl.Input(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH, name='sprs_branch_op') # Branch operation
        self.epcr = pyrtl.Input(bitwidth=width, name='sprs_epcr') # EPCR0
        self.eear = pyrtl.Input(bitwidth=width, name='sprs_eear') # EEAR0
        self.esr = pyrtl.Input(bitwidth=or1200_definitions.OR1200_SR_WIDTH, name='sprs_esr') # ESR0
        self.except_started = pyrtl.Input(bitwidth=1, name='sprs_except_started') # Exception was started
        self.spr_dat_cfgr = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_cfgr') # Data from CFGR
        self.spr_dat_rf = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_rf') # Data from RF
        self.spr_dat_npc = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_npc')  # Data from NPC
        self.spr_dat_ppc = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_ppc')  # Data from PPC

        self.epcr_we = pyrtl.Output(bitwidth=1,name='epcr_we')  # EPCR0 write enable
        self.eear_we = pyrtl.Output(bitwidth=1,name='eear_we')  # EEAR0 write enable
        self.esr_we = pyrtl.Output(bitwidth=1,name='esr_we')  # ESR0 write enable
        self.pc_we = pyrtl.Output(bitwidth=1,name='pc_we')  # PC write enable
        self.sr_we = pyrtl.WireVector(bitwidth=1)  # Write enable SR
        self.sr_we_out = pyrtl.Output(bitwidth=1,name='sprs_sr_we_out')  # Write enable SR
        self.to_sr = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH)  # Data to SR
        self.to_sr_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_SR_WIDTH,name='sprs_to_sr_out')  # Data to SR

        # To/from other RISC units
        self.spr_dat_pic = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_pic')  # Data from PIC
        self.spr_dat_tt = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_tt')  # Data from TT
        self.spr_dat_pm = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_pm')  # Data from PM
        self.spr_dat_du = pyrtl.Input(bitwidth=32, name='sprs_spr_dat_du')  # Data from DU
        self.spr_addr = pyrtl.WireVector(bitwidth=32)  # SPR Address
        self.spr_addr_out = pyrtl.Output(bitwidth=32,name='sprs_spr_addr_out')  # SPR Address

        self.spr_dat_o = pyrtl.WireVector(bitwidth=32)  # Data to unit
        self.spr_dat_o_out = pyrtl.Output(bitwidth=32,name='sprs_spr_dat_o_out')  # Data to unit

        self.spr_cs = pyrtl.WireVector(bitwidth=32)  # Unit select
        self.spr_cs_out = pyrtl.Output(bitwidth=32,name='sprs_spr_cs_out')  # Unit select

        self.spr_we = pyrtl.Output(bitwidth=1,name='sprs_spr_we')  # SPR write enable

        # To/from Debug Unit
        self.du_addr = pyrtl.Input(bitwidth=width, name='sprs_du_addr')  # Address
        self.du_dat_du = pyrtl.Input(bitwidth=width, name='sprs_du_dat_du')  # Data from DU to SPRS
        self.du_read = pyrtl.Input(bitwidth=1, name='sprs_du_read')  # Read qualifier
        self.du_write = pyrtl.Input(bitwidth=1, name='sprs_du_write')  # Write qualifier
        self.du_dat_cpu = pyrtl.Output(bitwidth=width,name='du_dat_cpu')  # Data from SPRS to DU

        # Internal regs & wires
        self.sr = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH) # SR
        self.sr_out = pyrtl.Output(bitwidth=or1200_definitions.OR1200_SR_WIDTH,name='sprs_sr_out')  # SR

        self.write_spr = pyrtl.WireVector(bitwidth=1) #, name='write_spr')  # Write SPR
        self.read_spr = pyrtl.WireVector(bitwidth=1) #, name='read+spr') # Read SPR
        self.to_wbmux = pyrtl.WireVector(bitwidth=width) #, name='to_wbmux') # For l.mfspr
        self.to_wbmux_out = pyrtl.Output(bitwidth=width,name='sprs_to_wbmux_out') # For l.mfspr

        self.cfgr_sel = pyrtl.WireVector(bitwidth=1) #, name='cfgr_sel') # Select for cfg regs
        self.rf_sel = pyrtl.WireVector(bitwidth=1) #, name='rf_sel') # Select for for RF
        self.npc_sel = pyrtl.WireVector(bitwidth=1) #, name='npc_sel') # Select for for NPC
        self.ppc_sel = pyrtl.WireVector(bitwidth=1) #, name='ppc_sel') # Select for for PPC
        self.sr_sel = pyrtl.WireVector(bitwidth=1) #, name='sr_sel') # Select for for SR
        self.epcr_sel = pyrtl.WireVector(bitwidth=1) #, name='epcr_sel') # Select for for EPCR0
        self.eear_sel = pyrtl.WireVector(bitwidth=1) #, name='eear_sel') # Select for for EEAR0
        self.esr_sel = pyrtl.WireVector(bitwidth=1) #, name='esr_sel') # Select for for ESR0
        self.sys_data = pyrtl.WireVector(bitwidth=32) #, name='sys_data') # Read data from system SPRs
        self.du_access = pyrtl.WireVector(bitwidth=1) #, name='du_access') # Debug unit access
        self.sprs_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH) #, name='sprs_op') # ALU operation
        self.unqualified_cs = pyrtl.WireVector(bitwidth=32) #, name='unqualified_cs') # Unqualified chip selects
        self.flag = pyrtl.Output(bitwidth=1,name='flag')
        self.carry = pyrtl.Output(bitwidth=1,name='carry')

        self.sr_out <<= self.sr
        self.sr_we_out <<= self.sr_we
        self.to_sr_out <<= self.to_sr
        self.to_wbmux_out <<= self.to_wbmux
        self.spr_addr_out <<= self.spr_addr
        self.spr_cs_out <<= self.spr_cs
        self.spr_dat_o_out <<= self.spr_dat_o

        # Decide if it is debug unit access
        self.du_access <<= self.du_read | self.du_write

        # Generate sprs opcode
        self.sprs_op <<= pyrtl.select(self.du_write, or1200_definitions.OR1200_ALUOP_MTSR, pyrtl.select(self.du_read, or1200_definitions.OR1200_ALUOP_MFSR, self.alu_op))

        # Generate SPR address from base address and offset
        # OR from debug unit address
        self.spr_addr <<= pyrtl.select(self.du_access, self.du_addr, (self.addrbase | self.addrofs.zero_extended(32)))

        # SPR is written by debug unit or by l.mtspr
        self.spr_dat_o <<= pyrtl.select(self.du_write, self.du_dat_du, self.dat_i)

        # debug unit data input:
        #  - write into debug unit SPRs by debug unit itself
        #  - read of SPRS by debug unit
        #  - write into debug unit SPRs by l.mtspr
        self.du_dat_cpu <<= pyrtl.select(self.du_write, self.du_dat_du, pyrtl.select(self.du_read, self.to_wbmux, self.dat_i))

        # Write into SPRs when l.mtspr
        self.spr_we <<= self.du_write | self.write_spr

        # Qualify chip selects
        self.spr_cs <<= self.unqualified_cs & pyrtl.concat_list(32*[self.read_spr | self.write_spr])

        to_sr = [i for i in self.to_sr]
        # What to write into SR
        to_sr[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO + 1] = pyrtl.select((self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE), self.esr[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO + 1], pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel), pyrtl.concat(or1200_definitions.ONE, self.spr_dat_o[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO]), self.sr[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO + 1]))
        
        to_sr[or1200_definitions.OR1200_SR_CY: or1200_definitions.OR1200_SR_CY + 1] = pyrtl.select((self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE), self.esr[or1200_definitions.OR1200_SR_CY: or1200_definitions.OR1200_SR_CY + 1], pyrtl.select(self.cy_we, self.cyforw, pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel), self.spr_dat_o[or1200_definitions.OR1200_SR_CY], self.sr[or1200_definitions.OR1200_SR_CY])))

        to_sr[or1200_definitions.OR1200_SR_F: or1200_definitions.OR1200_SR_F + 1] = pyrtl.select((self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE), self.esr[or1200_definitions.OR1200_SR_F], pyrtl.select(self.flag_we, self.flagforw, pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel), self.spr_dat_o[or1200_definitions.OR1200_SR_F], self.sr[or1200_definitions.OR1200_SR_F])))


        to_sr[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1] = pyrtl.select((self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE), self.esr[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1], pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel), self.spr_dat_o[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1], self.sr[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1]))

        self.to_sr <<= pyrtl.concat(*reversed(to_sr))
        
        # Selects for system SPRs
        self.cfgr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[4:11] == or1200_definitions.OR1200_SPR_CFGR))
        self.rf_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[5:11] == or1200_definitions.OR1200_SPR_RF))
        self.npc_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_NPC))
        self.ppc_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_PPC))
        self.sr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_SR))
        self.epcr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_EPCR))
        self.eear_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_EEAR))
        self.esr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val], (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_ESR))

        # Write enables for system SPRs
        self.sr_we <<= pyrtl.rtl_all(self.write_spr, self.sr_sel) | (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE) | self.flag_we | self.cy_we
        self.pc_we <<= pyrtl.rtl_all(self.write_spr, (self.npc_sel | self.ppc_sel))
        self.epcr_we <<= pyrtl.rtl_all(self.write_spr, self.epcr_sel)
        self.eear_we <<= pyrtl.rtl_all(self.write_spr, self.eear_sel)
        self.esr_we <<= pyrtl.rtl_all(self.write_spr, self.esr_sel)

        # Output from system SPRs
        self.sys_data <<= (self.spr_dat_cfgr & pyrtl.concat_list(32*[self.read_spr & self.cfgr_sel])) |\
        (self.spr_dat_rf & pyrtl.concat_list(32*[self.read_spr & self.rf_sel])) |\
        (self.spr_dat_npc & pyrtl.concat_list(32*[self.read_spr & self.npc_sel])) |\
        (self.spr_dat_ppc & pyrtl.concat_list(32*[self.read_spr & self.ppc_sel])) |\
        (pyrtl.concat((pyrtl.Const(32) - pyrtl.concat_list(or1200_definitions.OR1200_SR_WIDTH * [or1200_definitions.ZERO])),self.sr) \
          & (pyrtl.concat_list(32 * [self.read_spr & self.sr_sel]))) |\
         (self.epcr & (pyrtl.concat_list(32 * [self.read_spr & self.epcr_sel])))|\
         (self.eear & pyrtl.concat_list(32 * [self.read_spr & self.eear_sel]))|\
        (pyrtl.concat((pyrtl.Const(32) - pyrtl.concat_list(or1200_definitions.OR1200_SR_WIDTH * [or1200_definitions.ZERO])),self.esr) \
         & (pyrtl.concat_list(32 * [self.read_spr & self.esr_sel])))

        # Flag alias
        self.flag <<= self.sr[or1200_definitions.OR1200_SR_F]

        # Carry alias
        self.carry <<= self.sr[or1200_definitions.OR1200_SR_CY]

        # initialize all the parts
        superReg = SuperReg()
        minterface = Minterface()
        decodingGroups = DecodingGroups()
        
        superReg.rst <<= self.rst
        superReg.sr_we <<= self.sr_we
        superReg.except_started <<= self.except_started
        superReg.to_sr <<= self.to_sr
        self.sr <<= superReg.sr
        minterface.sprs_op <<= self.sprs_op
        minterface.spr_addr <<= self.spr_addr
        minterface.sys_data <<= self.sys_data
        minterface.spr_dat_pic <<= self.spr_dat_pic
        minterface.spr_dat_pm <<= self.spr_dat_pm
        minterface.spr_dat_du <<= self.spr_dat_du
        minterface.spr_dat_tt <<= self.spr_dat_tt
        self.to_wbmux <<= minterface.to_wbmux
        self.write_spr <<= minterface.write_spr
        self.read_spr <<= minterface.read_spr
        decodingGroups.spr_addr <<= self.spr_addr
        self.unqualified_cs <<= decodingGroups.unqualified_cs


class Or1200sprs_wire(object):
    def __init__(self):
        # Internal CPU interface
        self.rst = pyrtl.WireVector(bitwidth=1, name='sprs_rst')  # Reset
        self.flagforw = pyrtl.WireVector(bitwidth=1, name='sprs_flagforw')  # From ALU
        self.flag_we = pyrtl.WireVector(bitwidth=1, name='sprs_flag_we')  # From ALU
        self.cyforw = pyrtl.WireVector(bitwidth=1, name='sprs_cyforw')  # From ALU
        self.cy_we = pyrtl.WireVector(bitwidth=1, name='sprs_cy_we')  # From ALU
        self.addrbase = pyrtl.WireVector(bitwidth=width, name='sprs_addrbase')  # SPR base address
        self.addrofs = pyrtl.WireVector(bitwidth=16, name='sprs_addrofs')  # SPR offset
        self.dat_i = pyrtl.WireVector(bitwidth=width, name='sprs_dat_i')  # SPR write data
        self.alu_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH,
                                       name='sprs_alu_op')  # ALU operation
        self.branch_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_BRANCHOP_WIDTH,
                                          name='sprs_branch_op')  # Branch operation
        self.epcr = pyrtl.WireVector(bitwidth=width, name='sprs_epcr')  # EPCR0
        self.eear = pyrtl.WireVector(bitwidth=width, name='sprs_eear')  # EEAR0
        self.esr = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH, name='sprs_esr')  # ESR0
        self.except_started = pyrtl.WireVector(bitwidth=1, name='sprs_except_started')  # Exception was started
        self.spr_dat_cfgr = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_cfgr')  # Data from CFGR
        self.spr_dat_rf = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_rf')  # Data from RF
        self.spr_dat_npc = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_npc')  # Data from NPC
        self.spr_dat_ppc = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_ppc')  # Data from PPC

        self.epcr_we = pyrtl.WireVector(bitwidth=1, name='epcr_we')  # EPCR0 write enable
        self.eear_we = pyrtl.WireVector(bitwidth=1, name='eear_we')  # EEAR0 write enable
        self.esr_we = pyrtl.WireVector(bitwidth=1, name='esr_we')  # ESR0 write enable
        self.pc_we = pyrtl.WireVector(bitwidth=1, name='pc_we')  # PC write enable
        self.sr_we = pyrtl.WireVector(bitwidth=1)  # Write enable SR
        self.sr_we_out = pyrtl.WireVector(bitwidth=1, name='sprs_sr_we_out')  # Write enable SR
        self.to_sr = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH)  # Data to SR
        self.to_sr_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH,
                                          name='sprs_to_sr_out')  # Data to SR

        # To/from other RISC units
        self.spr_dat_pic = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_pic')  # Data from PIC
        self.spr_dat_tt = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_tt')  # Data from TT
        self.spr_dat_pm = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_pm')  # Data from PM
        self.spr_dat_du = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_du')  # Data from DU
        self.spr_addr = pyrtl.WireVector(bitwidth=32)  # SPR Address
        self.spr_addr_out = pyrtl.WireVector(bitwidth=32, name='sprs_spr_addr_out')  # SPR Address

        self.spr_dat_o = pyrtl.WireVector(bitwidth=32)  # Data to unit
        self.spr_dat_o_out = pyrtl.WireVector(bitwidth=32, name='sprs_spr_dat_o_out')  # Data to unit

        self.spr_cs = pyrtl.WireVector(bitwidth=32)  # Unit select
        self.spr_cs_out = pyrtl.WireVector(bitwidth=32, name='sprs_spr_cs_out')  # Unit select

        self.spr_we = pyrtl.WireVector(bitwidth=1, name='sprs_spr_we')  # SPR write enable

        # To/from Debug Unit
        self.du_addr = pyrtl.WireVector(bitwidth=width, name='sprs_du_addr')  # Address
        self.du_dat_du = pyrtl.WireVector(bitwidth=width, name='sprs_du_dat_du')  # Data from DU to SPRS
        self.du_read = pyrtl.WireVector(bitwidth=1, name='sprs_du_read')  # Read qualifier
        self.du_write = pyrtl.WireVector(bitwidth=1, name='sprs_du_write')  # Write qualifier
        self.du_dat_cpu = pyrtl.WireVector(bitwidth=width, name='sprs_du_dat_cpu')  # Data from SPRS to DU

        # Internal regs & wires
        self.sr = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH)  # SR
        self.sr_out = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH, name='sprs_sr')  # SR

        self.write_spr = pyrtl.WireVector(bitwidth=1)  # , name='write_spr')  # Write SPR
        self.read_spr = pyrtl.WireVector(bitwidth=1)  # , name='read+spr') # Read SPR
        self.to_wbmux = pyrtl.WireVector(bitwidth=width)  # , name='to_wbmux') # For l.mfspr
        self.to_wbmux_out = pyrtl.WireVector(bitwidth=width, name='sprs_to_wbmux_out')  # For l.mfspr

        self.cfgr_sel = pyrtl.WireVector(bitwidth=1)  # , name='cfgr_sel') # Select for cfg regs
        self.rf_sel = pyrtl.WireVector(bitwidth=1)  # , name='rf_sel') # Select for for RF
        self.npc_sel = pyrtl.WireVector(bitwidth=1)  # , name='npc_sel') # Select for for NPC
        self.ppc_sel = pyrtl.WireVector(bitwidth=1)  # , name='ppc_sel') # Select for for PPC
        self.sr_sel = pyrtl.WireVector(bitwidth=1)  # , name='sr_sel') # Select for for SR
        self.epcr_sel = pyrtl.WireVector(bitwidth=1)  # , name='epcr_sel') # Select for for EPCR0
        self.eear_sel = pyrtl.WireVector(bitwidth=1)  # , name='eear_sel') # Select for for EEAR0
        self.esr_sel = pyrtl.WireVector(bitwidth=1)  # , name='esr_sel') # Select for for ESR0
        self.sys_data = pyrtl.WireVector(bitwidth=32)  # , name='sys_data') # Read data from system SPRs
        self.du_access = pyrtl.WireVector(bitwidth=1)  # , name='du_access') # Debug unit access
        self.sprs_op = pyrtl.WireVector(
            bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH)  # , name='sprs_op') # ALU operation
        self.unqualified_cs = pyrtl.WireVector(bitwidth=32)  # , name='unqualified_cs') # Unqualified chip selects
        self.flag = pyrtl.WireVector(bitwidth=1, name='sprs_flag')
        self.carry = pyrtl.WireVector(bitwidth=1, name='sprs_carry')

        self.sr_out <<= self.sr
        self.sr_we_out <<= self.sr_we
        self.to_sr_out <<= self.to_sr
        self.to_wbmux_out <<= self.to_wbmux
        self.spr_addr_out <<= self.spr_addr
        self.spr_cs_out <<= self.spr_cs
        self.spr_dat_o_out <<= self.spr_dat_o

        # Decide if it is debug unit access
        self.du_access <<= self.du_read | self.du_write

        # Generate sprs opcode
        self.sprs_op <<= pyrtl.select(self.du_write, or1200_definitions.OR1200_ALUOP_MTSR,
                                      pyrtl.select(self.du_read, or1200_definitions.OR1200_ALUOP_MFSR, self.alu_op))

        # Generate SPR address from base address and offset
        # OR from debug unit address
        self.spr_addr <<= pyrtl.select(self.du_access, self.du_addr, (self.addrbase | self.addrofs.zero_extended(32)))

        # SPR is written by debug unit or by l.mtspr
        self.spr_dat_o <<= pyrtl.select(self.du_write, self.du_dat_du, self.dat_i)

        # debug unit data input:
        #  - write into debug unit SPRs by debug unit itself
        #  - read of SPRS by debug unit
        #  - write into debug unit SPRs by l.mtspr
        self.du_dat_cpu <<= pyrtl.select(self.du_write, self.du_dat_du,
                                         pyrtl.select(self.du_read, self.to_wbmux, self.dat_i))

        # Write into SPRs when l.mtspr
        self.spr_we <<= self.du_write | self.write_spr

        # Qualify chip selects
        self.spr_cs <<= self.unqualified_cs & pyrtl.concat_list(32 * [self.read_spr | self.write_spr])

        to_sr = [i for i in self.to_sr]
        # What to write into SR
        to_sr[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO + 1] = pyrtl.select(
            (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE),
            self.esr[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO + 1],
            pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel), pyrtl.concat(or1200_definitions.ONE,
                                                                                  self.spr_dat_o[
                                                                                  or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO]),
                         self.sr[or1200_definitions.OR1200_SR_OV: or1200_definitions.OR1200_SR_FO + 1]))

        to_sr[or1200_definitions.OR1200_SR_CY: or1200_definitions.OR1200_SR_CY + 1] = pyrtl.select(
            (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE),
            self.esr[or1200_definitions.OR1200_SR_CY: or1200_definitions.OR1200_SR_CY + 1],
            pyrtl.select(self.cy_we, self.cyforw, pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel),
                                                               self.spr_dat_o[or1200_definitions.OR1200_SR_CY],
                                                               self.sr[or1200_definitions.OR1200_SR_CY])))

        to_sr[or1200_definitions.OR1200_SR_F: or1200_definitions.OR1200_SR_F + 1] = pyrtl.select(
            (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE), self.esr[or1200_definitions.OR1200_SR_F],
            pyrtl.select(self.flag_we, self.flagforw, pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel),
                                                                   self.spr_dat_o[or1200_definitions.OR1200_SR_F],
                                                                   self.sr[or1200_definitions.OR1200_SR_F])))

        to_sr[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1] = pyrtl.select(
            (self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE),
            self.esr[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1],
            pyrtl.select(pyrtl.rtl_all(self.write_spr, self.sr_sel),
                         self.spr_dat_o[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1],
                         self.sr[or1200_definitions.OR1200_SR_SM: or1200_definitions.OR1200_SR_CE + 1]))

        self.to_sr <<= pyrtl.concat(*reversed(to_sr))

        # Selects for system SPRs
        self.cfgr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                        (self.spr_addr[4:11] == or1200_definitions.OR1200_SPR_CFGR))
        self.rf_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                      (self.spr_addr[5:11] == or1200_definitions.OR1200_SPR_RF))
        self.npc_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                       (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_NPC))
        self.ppc_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                       (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_PPC))
        self.sr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                      (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_SR))
        self.epcr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                        (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_EPCR))
        self.eear_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                        (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_EEAR))
        self.esr_sel <<= pyrtl.rtl_all(self.spr_cs[or1200_definitions.OR1200_SPR_GROUP_SYS.val],
                                       (self.spr_addr[0:11] == or1200_definitions.OR1200_SPR_ESR))

        # Write enables for system SPRs
        self.sr_we <<= pyrtl.rtl_all(self.write_spr, self.sr_sel) | (
                    self.branch_op == or1200_definitions.OR1200_BRANCHOP_RFE) | self.flag_we | self.cy_we
        self.pc_we <<= pyrtl.rtl_all(self.write_spr, (self.npc_sel | self.ppc_sel))
        self.epcr_we <<= pyrtl.rtl_all(self.write_spr, self.epcr_sel)
        self.eear_we <<= pyrtl.rtl_all(self.write_spr, self.eear_sel)
        self.esr_we <<= pyrtl.rtl_all(self.write_spr, self.esr_sel)

        # Output from system SPRs
        self.sys_data <<= (self.spr_dat_cfgr & pyrtl.concat_list(32 * [self.read_spr & self.cfgr_sel])) | \
                          (self.spr_dat_rf & pyrtl.concat_list(32 * [self.read_spr & self.rf_sel])) | \
                          (self.spr_dat_npc & pyrtl.concat_list(32 * [self.read_spr & self.npc_sel])) | \
                          (self.spr_dat_ppc & pyrtl.concat_list(32 * [self.read_spr & self.ppc_sel])) | \
                          (pyrtl.concat((pyrtl.Const(32) - pyrtl.concat_list(
                              or1200_definitions.OR1200_SR_WIDTH * [or1200_definitions.ZERO])), self.sr) \
                           & (pyrtl.concat_list(32 * [self.read_spr & self.sr_sel]))) | \
                          (self.epcr & (pyrtl.concat_list(32 * [self.read_spr & self.epcr_sel]))) | \
                          (self.eear & pyrtl.concat_list(32 * [self.read_spr & self.eear_sel])) | \
                          (pyrtl.concat((pyrtl.Const(32) - pyrtl.concat_list(
                              or1200_definitions.OR1200_SR_WIDTH * [or1200_definitions.ZERO])), self.esr) \
                           & (pyrtl.concat_list(32 * [self.read_spr & self.esr_sel])))

        # Flag alias
        self.flag <<= self.sr[or1200_definitions.OR1200_SR_F]

        # Carry alias
        self.carry <<= self.sr[or1200_definitions.OR1200_SR_CY]

        # initialize all the parts
        superReg = SuperReg()
        minterface = Minterface()
        decodingGroups = DecodingGroups()

        superReg.rst <<= self.rst
        superReg.sr_we <<= self.sr_we
        superReg.except_started <<= self.except_started
        superReg.to_sr <<= self.to_sr
        self.sr <<= superReg.sr
        minterface.sprs_op <<= self.sprs_op
        minterface.spr_addr <<= self.spr_addr
        minterface.sys_data <<= self.sys_data
        minterface.spr_dat_pic <<= self.spr_dat_pic
        minterface.spr_dat_pm <<= self.spr_dat_pm
        minterface.spr_dat_du <<= self.spr_dat_du
        minterface.spr_dat_tt <<= self.spr_dat_tt
        self.to_wbmux <<= minterface.to_wbmux
        self.write_spr <<= minterface.write_spr
        self.read_spr <<= minterface.read_spr
        decodingGroups.spr_addr <<= self.spr_addr
        self.unqualified_cs <<= decodingGroups.unqualified_cs

# Decoding of groups
class DecodingGroups(object):
    def __init__(self):
        self.spr_addr = pyrtl.WireVector(bitwidth=32)  # SPR Address

        self.unqualified_cs = pyrtl.WireVector(bitwidth=32)  # Unqualified chip selects

        with pyrtl.conditional_assignment:
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(0, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000000000001,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(1, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000000000010,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(2, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000000000100,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(3, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000000001000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(4, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000000010000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(5, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000000100000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(6, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000001000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(7, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000010000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(8, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000000100000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(9, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000001000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(10, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000010000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(11, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000000100000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(12, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000001000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(13, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000010000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(14, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000000100000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(15, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000001000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(16, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000010000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(17, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000000100000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(18, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000001000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(19, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000010000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(20, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000000100000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(21, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000001000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(22, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000010000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(23, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000000100000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(24, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000001000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(25, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000010000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(26, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00000100000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(27, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00001000000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(28, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00010000000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(29, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b00100000000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(30, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b01000000000000000000000000000000,bitwidth=32)
            with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == pyrtl.Const(31, bitwidth=or1200_definitions.OR1200_SPR_GROUP_WIDTH):
               self.unqualified_cs |= pyrtl.Const(0b10000000000000000000000000000000,bitwidth=32)


# Supervision register
class SuperReg(object):
    def __init__(self):
        self.rst = pyrtl.WireVector(bitwidth=1)  # Reset
        self.sr_we = pyrtl.WireVector(bitwidth=1)  # Write enable SR
        self.except_started = pyrtl.WireVector(bitwidth=1)  # Exception was started
        self.to_sr = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_SR_WIDTH)  # Data to SR
        self.sr = pyrtl.Register(bitwidth=or1200_definitions.OR1200_SR_WIDTH)  # SR

        sr = [i for i in self.sr]
        with pyrtl.conditional_assignment:
            with self.rst:
                self.sr.next |= pyrtl.concat(pyrtl.Const(0b1,bitwidth=1), or1200_definitions.OR1200_SR_EPH_DEF,\
                pyrtl.concat_list((or1200_definitions.OR1200_SR_WIDTH - 3)*[pyrtl.Const(0b0,bitwidth=1)]),\
                pyrtl.Const(0b1,bitwidth=1)) # #1
            with self.except_started:
                sr[or1200_definitions.OR1200_SR_SM] = pyrtl.Const(0b1)
                sr[or1200_definitions.OR1200_SR_TEE] = pyrtl.Const(0b0)
                sr[or1200_definitions.OR1200_SR_IEE] = pyrtl.Const(0b0)
                sr[or1200_definitions.OR1200_SR_DME] = pyrtl.Const(0b0)
                sr[or1200_definitions.OR1200_SR_IME] = pyrtl.Const(0b0)
                self.sr.next |= pyrtl.concat(*reversed(sr))
                # self.sr = pyrtl.bitfield_update(self.sr, or1200_definitions.OR1200_SR_SM, or1200_definitions.OR1200_SR_SM+1, pyrtl.Const(0b1, bitwidth=1))
                # self.sr = pyrtl.bitfield_update(self.sr, or1200_definitions.OR1200_SR_TEE, or1200_definitions.OR1200_SR_TEE+1, pyrtl.Const(0b0, bitwidth=1))
                # self.sr = pyrtl.bitfield_update(self.sr, or1200_definitions.OR1200_SR_IEE, or1200_definitions.OR1200_SR_IEE+1, pyrtl.Const(0b0, bitwidth=1))
                # self.sr = pyrtl.bitfield_update(self.sr, or1200_definitions.OR1200_SR_DME, or1200_definitions.OR1200_SR_DME+1, pyrtl.Const(0b0, bitwidth=1))
                # self.sr = pyrtl.bitfield_update(self.sr, or1200_definitions.OR1200_SR_IME, or1200_definitions.OR1200_SR_IME+1, pyrtl.Const(0b0, bitwidth=1))
            with self.sr_we:
                self.sr.next |= self.to_sr[0:or1200_definitions.OR1200_SR_WIDTH]      # #1


# MTSPR/MFSPR interface
class Minterface(object):
    def __init__(self):
        self.sprs_op = pyrtl.WireVector(bitwidth=or1200_definitions.OR1200_ALUOP_WIDTH)  # ALU operation
        self.spr_addr = pyrtl.WireVector(bitwidth=32)  # SPR Address
        self.sys_data = pyrtl.WireVector(bitwidth=32)  # Read data from system SPRs
        self.spr_dat_pic = pyrtl.WireVector(bitwidth=32)  # Data from PIC
        self.spr_dat_pm = pyrtl.WireVector(bitwidth=32)  # Data from PM
        self.spr_dat_du = pyrtl.WireVector(bitwidth=32)  # Data from DU
        self.spr_dat_tt = pyrtl.WireVector(bitwidth=32)  # Data from TT

        self.to_wbmux = pyrtl.WireVector(bitwidth=width)  # For l.mfspr
        self.write_spr = pyrtl.WireVector(bitwidth=1)  # Write SPR
        self.read_spr = pyrtl.WireVector(bitwidth=1)  # Read SPR
        
        with pyrtl.conditional_assignment:
            with self.sprs_op == or1200_definitions.OR1200_ALUOP_MTSR:
                self.to_wbmux |= pyrtl.Const(0b0, bitwidth=32)
                self.write_spr |= pyrtl.Const(0b1, bitwidth=1)
                self.read_spr |= pyrtl.Const(0b0, bitwidth=1)
            with self.sprs_op == or1200_definitions.OR1200_ALUOP_MFSR:
                with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == or1200_definitions.OR1200_SPR_GROUP_TT:
                    self.to_wbmux |= self.spr_dat_tt
                with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == or1200_definitions.OR1200_SPR_GROUP_PIC:
                    self.to_wbmux |= self.spr_dat_pic
                with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == or1200_definitions.OR1200_SPR_GROUP_PM:
                    self.to_wbmux |= self.spr_dat_pm
                with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == or1200_definitions.OR1200_SPR_GROUP_DU:
                    self.to_wbmux |= self.spr_dat_du
                with self.spr_addr[or1200_definitions.OR1200_SPR_GROUP_BITS] == or1200_definitions.OR1200_SPR_GROUP_SYS:
                    self.to_wbmux |= self.sys_data
                with pyrtl.otherwise:
                    self.to_wbmux |= pyrtl.Const(0b0, bitwidth=32)
                self.write_spr |= pyrtl.Const(0b0, bitwidth=1)
                self.read_spr |= pyrtl.Const(0b1, bitwidth=1)
            with pyrtl.otherwise:
                self.write_spr |= pyrtl.Const(0b0, bitwidth=1)
                self.read_spr |= pyrtl.Const(0b0, bitwidth=1)
                self.to_wbmux |= pyrtl.Const(0b0, bitwidth=32)

def simple_test(sim, inputs, num=15):
    muxes_info = dict()
    for mux in sim.block.logic_subset('x'):
        muxes_info[mux.args[0].name] = list()
    for i in range(num):
        sim.step(inputs)
        for mux in sim.block.logic_subset('x'):
            present_value = sim.inspect(mux.args[0].name)
            muxes_info[mux.args[0].name].append(present_value)
    for k, v in muxes_info.items():
        print(k, v)

if __name__ == '__main__':
    or1200sprs = Or1200sprs()
    sim = pyrtl.GPUSim_now.GPUSim('sprs')

    com = pyrtl.CompiledSimulation()

    input_width = []
    from pyrtl.wire import Input

    IN = pyrtl.working_block().wirevector_subset(Input)
    for inn in IN:
        name = inn.name
        width = inn.bitwidth
        input_width.append([name, width])
    import random

    max_ = 0
    com_time = 0
    ess_time = 0
    num = 1
    for i in range(num):
        print(i)

        inputs_random = {}
        inputs_select = {}
        inputs_old = {}
        inputs_ = {}

        for inp in input_width:
            inputs_random[inp[0]] = []
            inputs_select[inp[0]] = []
            result = random.randint(0, 2 ** inp[1] - 1)
            inputs_old[inp[0]] = result

        for j in range(131072):
            for inp in input_width:
                result = random.randint(0, 2 ** inp[1] - 1)
                inputs_[inp[0]] = result
                inputs_random[inp[0]].append(result)
            if random.random() < 0.2:
                for name in inputs_old:
                    inputs_select[name].append(inputs_old[name])
            else:
                for name in inputs_:
                    inputs_select[name].append(inputs_[name])
                    inputs_old[name] = inputs_[name]
        time1 = com.step_multiple(inputs_select)

    sim.make_input(inputs_select)